package com.frank.subject.domain.service.impl;

import com.frank.subject.common.entity.PageResult;
import com.frank.common.enums.IsDeletedFlagEnum;
import com.frank.subject.domain.convert.SubjectInfoBoConverter;
import com.frank.subject.domain.entity.SubjectInfoBo;
import com.frank.subject.domain.entity.SubjectOptionBo;
import com.frank.subject.domain.handler.subject.SubjectTypeHandler;
import com.frank.subject.domain.handler.subject.SubjectTypeHandlerFactory;
import com.frank.subject.domain.service.SubjectDomainService;
import com.frank.subject.infra.basic.entity.SubjectInfo;
import com.frank.subject.infra.basic.entity.SubjectLabel;
import com.frank.subject.infra.basic.entity.SubjectMapping;
import com.frank.subject.infra.basic.service.SubjectInfoService;
import com.frank.subject.infra.basic.service.SubjectLabelService;
import com.frank.subject.infra.basic.service.SubjectMappingService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Frank Zou
 * @version v0.0.1
 * @date 2024/1/25 1:51 PM
 * @description
 */
@Service
public class SubjectDomainServiceImpl implements SubjectDomainService {

    private final SubjectInfoService subjectInfoService;

    private final SubjectTypeHandlerFactory subjectTypeHandlerFactory;

    private final SubjectMappingService subjectMappingService;

    private final SubjectLabelService subjectLabelService;

    public SubjectDomainServiceImpl(SubjectInfoService subjectInfoService,
                                    SubjectTypeHandlerFactory subjectTypeHandlerFactory,
                                    SubjectMappingService subjectMappingService,
                                    SubjectLabelService subjectLabelService) {
        this.subjectInfoService = subjectInfoService;
        this.subjectTypeHandlerFactory = subjectTypeHandlerFactory;
        this.subjectMappingService = subjectMappingService;
        this.subjectLabelService = subjectLabelService;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SubjectInfoBo subjectInfoBO) {
        SubjectInfo subjectInfo = SubjectInfoBoConverter.INSTANCE.convertBoToInfo(subjectInfoBO);
        subjectInfo.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        subjectInfoService.save(subjectInfo);
        // 将数据库返回的 Subject id 设置到 Bo 中
        subjectInfoBO.setId(subjectInfo.getId());
        // 使用工厂加策略模式添加题目的答案选项
        SubjectTypeHandler handler = subjectTypeHandlerFactory.getHandler(subjectInfo.getSubjectType());
        handler.add(subjectInfoBO);
        List<SubjectMapping> list = new LinkedList<>();
        // 添加题目和标签，类型的映射关系
        subjectInfoBO.getCatetoryIdList().forEach(categoryId -> {
            for (Integer labelId : subjectInfoBO.getLabelIdList()) {
                SubjectMapping subjectMapping = new SubjectMapping();
                subjectMapping.setSubjectId(subjectInfo.getId());
                subjectMapping.setLabelId(Long.valueOf(labelId));
                subjectMapping.setCategoryId(Long.valueOf(categoryId));
                subjectMapping.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
                list.add(subjectMapping);
            }
        });
        subjectMappingService.saveBatch(list);
    }

    @Override
    public PageResult<SubjectInfoBo> getSubjectPage(SubjectInfoBo subjectInfoBO) {
        PageResult<SubjectInfoBo> result = new PageResult<>();
        result.setCurrent(subjectInfoBO.getCurrent());
        result.setPageSize(subjectInfoBO.getPageSize());
        int start = (subjectInfoBO.getCurrent() - 1) * subjectInfoBO.getPageSize();
        SubjectInfo subjectInfo = SubjectInfoBoConverter.INSTANCE.convertBoToInfo(subjectInfoBO);
        int count = subjectInfoService.countByCondition(subjectInfo, subjectInfoBO.getLabelId(), subjectInfoBO.getCategoryId());
        if (count == 0) {
            return result;
        }
        List<SubjectInfo> subjectInfos = subjectInfoService.queryPage(subjectInfo, subjectInfoBO.getCategoryId(), subjectInfoBO.getLabelId(), start, subjectInfoBO.getPageSize());
        result.setRecords(SubjectInfoBoConverter.INSTANCE.convertEntitiesToBoList(subjectInfos));
        result.setTotal(count);
        return result;
    }

    @Override
    public SubjectInfoBo querySubjectInfo(SubjectInfoBo subjectInfoBO) {
        SubjectInfo subjectInfo = subjectInfoService.getById(subjectInfoBO.getId());
        if (subjectInfo == null) {
            return new SubjectInfoBo();
        }
        SubjectTypeHandler handler = subjectTypeHandlerFactory.getHandler(subjectInfo.getSubjectType());
        SubjectOptionBo subjectOptionBo = handler.query(subjectInfo.getId());
        SubjectInfoBo subjectInfoBo = SubjectInfoBoConverter.INSTANCE.convertEntityAndOptionToBo(subjectOptionBo, subjectInfo);
        SubjectMapping subjectMapping = new SubjectMapping();
        subjectMapping.setSubjectId(subjectInfoBo.getId());
        subjectMapping.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        List<Long> labelIds = subjectMappingService.queryLabelId(subjectMapping);
        if (!labelIds.isEmpty()){
            List<String> labelNames = subjectLabelService.queryBatchLabelByIds(labelIds).stream().map(SubjectLabel::getLabelName).collect(Collectors.toList());
            subjectInfoBo.setLabelNames(labelNames);
        }
        return subjectInfoBo;
    }
}
